{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "vlIwqnYdGPc2"
   },
   "source": "# Scheduling Agent with Agno(Phidata), Nebius Token Factory and Cal.com\n\n[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1YbNqBKFE9BVSF0EHz2jVHB5x7y3pSS27?usp=sharing)\n\nThis notebook demonstrates how to build a scheduling assistant using Agno (PhiData) and Nebius Token Factory. The agent, powered by the meta-llama/Meta-Llama-3.1-70B-Instruct model, integrates with Cal.com to manage bookings, check available slots, and more.\n\nNebius Token Factory provides access to many state-of-the-art LLM models. Check out the full list of models here."
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Ghkl3fVbGlhM"
   },
   "source": [
    "## Install Dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "GBJiAN9OGMG5"
   },
   "outputs": [],
   "source": [
    "!pip install -qq agno python-dotenv requests pytz"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ybg3wEA9G0eM"
   },
   "source": [
    "## Setting Up Environment Variables\n",
    "\n",
    "Visit https://studio.nebius.ai/ and sign up to get a Nebius API key. You’ll also need a Cal.com API key from https://cal.com/settings/developer/api-keys.\n",
    "\n",
    "For security, we’ll prompt you to enter your Nebius and Cal.com API keys instead of hardcoding them, since Colab doesn’t natively support .env files."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "id": "6DAf68XRHkR9"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"NEBIUS_API_KEY\"] = \"Your Nebius API Key\"\n",
    "os.environ[\"CALCOM_API_KEY\"]=\"Your Cal.com API Key\"\n",
    "os.environ[\"CALCOM_EVENT_TYPE_ID\"]=\"Your Cal.com Event Type\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Ct49hkDOPq5O",
    "outputId": "6eef2f9b-212c-4538-bd50-de4cae6797ca"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- Event IDs ---\n",
      "ID: 870697, Title: 15 Min Meeting\n",
      "ID: 870698, Title: 30 Min Meeting\n",
      "ID: 870699, Title: Collaboration with Arindam\n",
      "\n",
      "Total Event Types Found: 3\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import requests\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# Load environment variables\n",
    "load_dotenv()\n",
    "\n",
    "api_key = os.environ[\"CALCOM_API_KEY\"]\n",
    "url = \"https://api.cal.com/v2/event-types\"\n",
    "headers = {\"Authorization\": f\"Bearer {api_key}\"}\n",
    "\n",
    "response = requests.get(url, headers=headers)\n",
    "\n",
    "data = response.json()\n",
    "\n",
    "event_types = data['data']['eventTypeGroups'][0]['eventTypes']\n",
    "\n",
    "print(\"--- Event IDs ---\")\n",
    "for event in event_types:\n",
    "    print(f\"ID: {event['id']}, Title: {event['title']}\")\n",
    "\n",
    "print(f\"\\nTotal Event Types Found: {len(event_types)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "4M0NL3-1LG2H"
   },
   "outputs": [],
   "source": [
    "import nest_asyncio\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "JrUS78jVIHrM"
   },
   "source": [
    "## Import Required Modules\n",
    "We import essential modules for working with dates, Agno, and Cal.com tools."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "zN5uvk7UIvAN"
   },
   "outputs": [],
   "source": [
    "from datetime import datetime, timedelta\n",
    "from agno.agent import Agent\n",
    "from agno.models.nebius import Nebius\n",
    "from agno.tools.calcom import CalComTools\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8tdbZ2HSJIf9"
   },
   "source": [
    "## Define Instructions for the Agent\n",
    "\n",
    "Set up the instructions that guide the agent’s scheduling capabilities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "dCiqQblqJR0x"
   },
   "outputs": [],
   "source": [
    "# Define instructions with current date\n",
    "INSTRUCTIONS = f\"\"\"You're a scheduling assistant. Today is {datetime.now()}.\n",
    "You can help users by:\n",
    "    - Finding available time slots using get_available_slots(start_date, end_date)\n",
    "    - Creating new bookings using create_booking(start_time, name, email)\n",
    "    - Managing existing bookings using get_upcoming_bookings(email)\n",
    "    - Rescheduling bookings using reschedule_booking(booking_uid, new_start_time, reason)\n",
    "    - Cancelling bookings using cancel_booking(booking_uid, reason)\n",
    "\n",
    "IMPORTANT STEPS for booking:\n",
    "1. First check available slots using get_available_slots\n",
    "2. Then create booking using create_booking with the exact start_time, name, and email provided\n",
    "3. Finally verify the booking was created using get_upcoming_bookings with the provided email\n",
    "\n",
    "When asked to book a call, you MUST:\n",
    "1. Call create_booking with the provided start_time, name, and email\n",
    "2. Then verify the booking using get_upcoming_bookings\n",
    "3. Confirm to the user whether the booking was successful\n",
    "\n",
    "Remember:\n",
    "- Dates should be in YYYY-MM-DD format\n",
    "- Times should be in YYYY-MM-DDTHH:MM:SS+TZ format (e.g., 2025-03-20T14:30:00+05:30)\n",
    "- Always confirm details before making changes\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7WjWtN3mJY0e"
   },
   "source": [
    "## Initialize the Cal.com Tools and Model\n",
    "\n",
    "Set up the Cal.com tools and Nebius AI model for the agent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "MGYGkda6Jhqh"
   },
   "outputs": [],
   "source": [
    "# Create the CalCom tools instance\n",
    "try:\n",
    "    calcom_tools = CalComTools(\n",
    "        user_timezone=\"Asia/Kolkata\",\n",
    "        api_key=os.environ[\"CALCOM_API_KEY\"],\n",
    "        event_type_id=os.environ[\"CALCOM_EVENT_TYPE_ID\"]\n",
    "    )\n",
    "except Exception as e:\n",
    "    print(f\"Error initializing CalCom tools: {e}\")\n",
    "    raise"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "-HSXH6poJqkl"
   },
   "source": [
    "## Create the Scheduling Agent\n",
    "Instantiate the agent with the defined instructions, model, and tools."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "dIWUeRFSJp4Z"
   },
   "outputs": [],
   "source": [
    "# Create the agent\n",
    "agent = Agent(\n",
    "    name=\"Calendar Assistant\",\n",
    "    instructions=[INSTRUCTIONS],\n",
    "    model=Nebius(\n",
    "        id=\"Qwen/Qwen3-30B-A3B\",\n",
    "        api_key=os.getenv(\"NEBIUS_API_KEY\") # Explicitly pass the API key\n",
    "    ),\n",
    "    tools=[calcom_tools],\n",
    "    show_tool_calls=True,\n",
    "    tool_choice=\"auto\",\n",
    "    markdown=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "FOyTlbySJ33S"
   },
   "source": [
    "## Run an Example Booking\n",
    "Test the agent by checking available slots and booking a call."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 417,
     "referenced_widgets": [
      "8c871ad7dad14f53bb1f6947a5c8b8f4",
      "c4704a1a99e04520bca1f8fea958f87f",
      "80002fe0aeb74c70831bcf919643248e",
      "5b9b81f154f9420c91d2dd9147a22ce3"
     ]
    },
    "id": "_0xgzbpRJ9Wa",
    "outputId": "99b011d6-3d18-409d-b513-ae01251d2935"
   },
   "outputs": [],
   "source": [
    "# Example function to book a call\n",
    "def book_example_call():\n",
    "    # Get today's date and tomorrow's date\n",
    "    today = datetime.now().strftime(\"%Y-%m-%d\")\n",
    "    tomorrow = (datetime.now() + timedelta(days=1)).strftime(\"%Y-%m-%d\")\n",
    "\n",
    "    # Check available slots\n",
    "    print(\"Checking available slots...\")\n",
    "    agent.print_response(f\"\"\"\n",
    "    Please check available slots between {today} and {tomorrow}\n",
    "    \"\"\")\n",
    "\n",
    "    # Book a specific slot\n",
    "    print(\"\\nAttempting to book a call...\")\n",
    "    agent.print_response(\"\"\"\n",
    "    Please book a call with these details:\n",
    "    - Start Time: 2025-03-22T22:30:00+05:30\n",
    "    - Name: Agno Agent Test\n",
    "    - Email: studioone.tech@gmail.com\n",
    "\n",
    "    After booking, please verify the booking exists.\n",
    "    \"\"\")\n",
    "\n",
    "# Run the example\n",
    "book_example_call()"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "5b9b81f154f9420c91d2dd9147a22ce3": {
     "model_module": "@jupyter-widgets/base",
     "model_module_version": "1.2.0",
     "model_name": "LayoutModel",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "80002fe0aeb74c70831bcf919643248e": {
     "model_module": "@jupyter-widgets/output",
     "model_module_version": "1.0.0",
     "model_name": "OutputModel",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/output",
      "_model_module_version": "1.0.0",
      "_model_name": "OutputModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/output",
      "_view_module_version": "1.0.0",
      "_view_name": "OutputView",
      "layout": "IPY_MODEL_5b9b81f154f9420c91d2dd9147a22ce3",
      "msg_id": "",
      "outputs": [
       {
        "data": {
         "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">▰▱▱▱▱▱▱</span> Thinking...\n<span style=\"color: #008080; text-decoration-color: #008080\">┏━ Message ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    Please book a call with these details:</span>                                                                      <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    - Start Time: 2025-03-22T22:30:00+05:30</span>                                                                     <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    - Name: Agno Agent Test</span>                                                                                     <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    - Email: studioone.tech@gmail.com</span>                                                                           <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    After booking, please verify the booking exists.</span>                                                            <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    </span>                                                                                                            <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛</span>\n</pre>\n",
         "text/plain": "\u001b[32m▰▱▱▱▱▱▱\u001b[0m Thinking...\n\u001b[36m┏━\u001b[0m\u001b[36m Message \u001b[0m\u001b[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[36m━┓\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    Please book a call with these details:\u001b[0m                                                                      \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    - Start Time: 2025-03-22T22:30:00+05:30\u001b[0m                                                                     \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    - Name: Agno Agent Test\u001b[0m                                                                                     \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    - Email: studioone.tech@gmail.com\u001b[0m                                                                           \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    After booking, please verify the booking exists.\u001b[0m                                                            \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    \u001b[0m                                                                                                            \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\u001b[0m\n"
        },
        "metadata": {},
        "output_type": "display_data"
       }
      ]
     }
    },
    "8c871ad7dad14f53bb1f6947a5c8b8f4": {
     "model_module": "@jupyter-widgets/output",
     "model_module_version": "1.0.0",
     "model_name": "OutputModel",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/output",
      "_model_module_version": "1.0.0",
      "_model_name": "OutputModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/output",
      "_view_module_version": "1.0.0",
      "_view_name": "OutputView",
      "layout": "IPY_MODEL_c4704a1a99e04520bca1f8fea958f87f",
      "msg_id": "",
      "outputs": [
       {
        "data": {
         "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">▰▰▰▰▰▰▱</span> Thinking...\n<span style=\"color: #008080; text-decoration-color: #008080\">┏━ Message ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    Please check available slots between 2025-03-21 and 2025-03-22</span>                                              <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span> <span style=\"color: #008000; text-decoration-color: #008000\">    </span>                                                                                                            <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┃</span>                                                                                                                 <span style=\"color: #008080; text-decoration-color: #008080\">┃</span>\n<span style=\"color: #008080; text-decoration-color: #008080\">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛</span>\n</pre>\n",
         "text/plain": "\u001b[32m▰▰▰▰▰▰▱\u001b[0m Thinking...\n\u001b[36m┏━\u001b[0m\u001b[36m Message \u001b[0m\u001b[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[36m━┓\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    Please check available slots between 2025-03-21 and 2025-03-22\u001b[0m                                              \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32m    \u001b[0m                                                                                                            \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m                                                                                                                 \u001b[36m┃\u001b[0m\n\u001b[36m┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\u001b[0m\n"
        },
        "metadata": {},
        "output_type": "display_data"
       }
      ]
     }
    },
    "c4704a1a99e04520bca1f8fea958f87f": {
     "model_module": "@jupyter-widgets/base",
     "model_module_version": "1.2.0",
     "model_name": "LayoutModel",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    }
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}